#ifndef __WIZ_DATATYPE_SIGNAL_SAFE_TEMPLATE_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_SIGNAL_SAFE_TEMPLATE_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"
#include "../../Core/Container/WizDataTypeList.hpp"
#include "../../Core/Container/WizDataTypeMultiMap.hpp"

namespace Wiz
{
    namespace Signal
    {
        namespace Safe
        {
            namespace Object
            {
                template<class ParamT> class Type;
            } /// end of namespace Object
            template<class ParamT> class Type;
        } /// end of namespace Safe
    } /// end of namespace Signal
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_SIGNAL_SAFE_TEMPLATE_HPP__SHANHAOBO_19800429__*/

#undef  WIZ_SIGNAL_PARAM_COUNT
#define WIZ_SIGNAL_PARAM_COUNT WIZ_MPP_REPEAT_FILE_COUNT
#if defined(WIZ_SIGNAL_PARAM_COUNT) && (WIZ_SIGNAL_PARAM_COUNT >= 0) && (WIZ_SIGNAL_PARAM_COUNT < 255)

namespace Wiz
{
    namespace Signal
    {
        namespace Safe
        {
            namespace Object
            {
                template<class RetT WIZ_COMMA_IF(WIZ_SIGNAL_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, class T)>
                class Type<RetT(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>
                {
                    typedef RetT                                                                            tRet;
                    typedef ::Wiz::Signal::Safe::Type<tRet(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>    tSafeSignal;
                    typedef ::Wiz::Function::Type<tRet(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>        tFunction;
                    typedef ::Wiz::MultiMap::Type<tSafeSignal*, tFunction>                                  tContainer;
                public:
                    Type(){}
                    virtual ~Type()
                    {
						this->Clear();
                    }
                public:
                    ::Wiz::Void::Type Record(tSafeSignal* SPtr, const tFunction& F)
                    {
						WIZ_ASSERT(::Wiz::IsValidPtr(SPtr));
                        m_Container.Insert(SPtr, F);
                    }
                    ::Wiz::Void::Type Remove(tSafeSignal* SPtr, const tFunction& F)
                    {
                        tContainer::tIterator Lower = m_Container.LowerBound(SPtr);
                        tContainer::tIteratorConst Upper = m_Container.UpperBound(SPtr);
                        for (; Lower != Upper; Lower++)
                        {
                            if (Lower.GetValue() == F)
                            {
								WIZ_ASSERT(::Wiz::IsValidPtr(Lower.GetIndex()));
                                m_Container.Erase(Lower);
                                return;
                            }
                        }
                    }
					::Wiz::Void::Type Clear()
					{
                        tContainer::tIterator Curr;
                        tContainer::tForEach  FE(Curr, m_Container);
                        while (FE.HasMoreElement())
                        {
							WIZ_ASSERT(::Wiz::IsValidPtr(Curr.GetIndex()));
                            Curr.GetIndex()->Unregister(Curr.GetValue());
                        }
						this->m_Container.Clear();
					}
                protected:
                    tContainer m_Container;
                }; /// end of class Type
            } /// end of namespace Object

            template<class RetT WIZ_COMMA_IF(WIZ_SIGNAL_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, class T)>
            class Type<RetT(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>
            {
                typedef RetT                                                                                        tRet;
                typedef ::Wiz::Set::Type<::Wiz::Function::Type<tRet(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>>  tContainer;
                typedef ::Wiz::Signal::Safe::Object::Type<tRet(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>        tObject;
                typedef ::Wiz::Function::Type<tRet(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T))>                    tFunction;
                friend class tObject;
            public:
                Type(){}
                virtual ~Type()
                {
                    this->Clear();
                }
            protected:
                ::Wiz::Void::Type Register(tFunction& F)
                {
                    m_Container.Insert(F);

                    tObject* OPtr = F.GetClassPtr<tObject>();
                    if (::Wiz::IsValidPtr(OPtr))
                    {
                        OPtr->Record(this, F);
                    }
                }
                ::Wiz::Void::Type Unregister(tFunction& F)
                {
                    tContainer::tIterator Itr = m_Container.Find(F);
                    if (Itr != m_Container.End())
                    {
                        m_Container.Erase(Itr);
                    }

                    tObject* OPtr = F.GetClassPtr<tObject>();
                    if (::Wiz::IsValidPtr(OPtr))
                    {
                        OPtr->Remove(this, F);
                    }
                }
            public:
                ::Wiz::Void::Type Register(tRet(*FuncPtr)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T)))
                {
                    Register(tFunction(FuncPtr));
                }
                ::Wiz::Void::Type Unregister(tRet(*FuncPtr)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T)))
                {
                    Unregister(tFunction(FuncPtr));
                }
                template<class U>
                ::Wiz::Void::Type Register(const U* C, tRet(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T)))
                {
                    Register(tFunction(C, FP));
                }
                template<class U>
                ::Wiz::Void::Type Unregister(const U* C, tRet(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T)))
                {
                    Unregister(tFunction(C, FP));
                }
                template<class U>
                ::Wiz::Void::Type Register(U* C)
                {
                    Register(tFunction(C));
                }
                template<class U>
                ::Wiz::Void::Type Unregister(U* C)
                {
                    Unregister(tFunction(C));
                }
            public:
                ::Wiz::Void::Type operator+=(tFunction& F)
                {
                    Register(F);
                }
                ::Wiz::Void::Type operator-=(tFunction& F)
                {
                    Unregister(F);
                }
                ::Wiz::Void::Type operator+=(tRet(*FuncPtr)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T)))
                {
                    this->Register(FuncPtr);
                }
                ::Wiz::Void::Type operator-=(tRet(*FuncPtr)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, T)))
                {
                    this->Unregister(FuncPtr);
                }
                template<class U>
                ::Wiz::Void::Type operator+=(U* C)
                {
                    this->Register(C);
                }
                template<class U>
                ::Wiz::Void::Type operator-=(U* C)
                {
                    this->Unregister(C);
                }
            public:
                ::Wiz::Void::Type operator()(WIZ_ENUM_PARAM_XY(WIZ_SIGNAL_PARAM_COUNT, T, A))
                {
                    this->SignalExecute(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, A));
                }
            public:
                ::Wiz::Void::Type Clear()
                {
                    tContainer::tIterator Curr;
                    tContainer::tForEach  FE(Curr, m_Container);
                    while (FE.HasMoreElement())
                    {
                        tObject* OPtr = Curr->GetClassPtr<tObject>();
                        if (::Wiz::IsValidPtr(OPtr))
                        {
                            OPtr->Remove(this, *Curr);
                        }
                    }

                    m_Container.Clear();
                }
            public:
            ::Wiz::Size::Type Size()
            {
                return m_Container.Size();
            }
            public:
                tContainer m_Container;
            protected:
                ::Wiz::Void::Type SignalExecute(WIZ_ENUM_PARAM_XY(WIZ_SIGNAL_PARAM_COUNT, T, A))
                {
                    tContainer::tForEachIter  FE(m_Container);
                    while (FE)
                    {
                        (*FE)(WIZ_ENUM_PARAM_X(WIZ_SIGNAL_PARAM_COUNT, A));
                        FE++;
                    }
                }
            };
        } /// end of namespace Safe
    } /// end of namespace Signal
} /// end of namespace Wiz


#endif /*WIZ_SIGNAL_PARAM_COUNT*/


